package informationretrieval;

import static informationretrieval.Constants.DEBUG;
import static informationretrieval.Constants.NAME_ID;

import java.io.FileWriter;
import java.io.IOException;

import org.apache.lucene.document.Document;

public class Log {

	// Class final variables
	private static final String TAG = Log.class.getSimpleName();
	private static final String START_END = "-============================================-";
	private static final String SEPERATOR = "**********************************************";
	private static final int EXIT_WITH_ERROR = 1;

	/**
	 * Prints the error message and the exception neatly to the error stream
	 * 
	 * @param fileName
	 *            The error message to display
	 * @param exception
	 *            The exception thrown
	 */
	public static synchronized void error(String fileName, Exception exception,
			boolean shouldExit) {
		System.err.println(START_END);
		System.err.println("A problem has occured in " + fileName);
		System.err.println(SEPERATOR);
		System.err.println("Exception " + exception + " with message -\n"
				+ exception.getMessage());
		System.err.println(SEPERATOR);
		System.err.println("Exception Stack trace -");
		StackTraceElement[] traces = exception.getStackTrace();
		for (int i = 0; i < traces.length; i++) {
			System.err.println(traces[i].toString());
		}
		System.err.println();
		System.err.println(START_END);
		if (shouldExit) {
			System.exit(EXIT_WITH_ERROR);
		}
	}

	/**
	 * Prints a message for trace
	 * 
	 * @param message
	 *            the message to be printed to the standard output
	 */
	public static synchronized void trace(String message) {
		if (DEBUG) {
			System.out.println(START_END);
			System.out.println(message);
			System.out.println(START_END);
		}
	}

	/**
	 * Helper function to write the results to the file as requested please note
	 * that the method receieve Writer object that is open and closed external.
	 * The function write the results per query and append it to the writer
	 * 
	 * @param writer
	 * @param result
	 * @param queryId
	 */
	public static void writeResultsToFile(FileWriter writer,
			SearchResult result, int queryId, double ndcg, double map) {
		// Method variables
		String stringDocId;
		String stringQueryId;
		String newLine = System.getProperty("line.separator");

		try {
			stringQueryId = String.format("q%s", queryId);

			if (result.getScoreDoc().length == 0) {
				writer.write(stringQueryId + ", dummy, 1, 0" + newLine);
			} else {
				for (int rank = 0; rank < result.getScoreDoc().length; rank++) {
					int docId = result.getScoreDoc()[rank].doc;
					float score = result.getScoreDoc()[rank].score;
					Document document = result.getDoc(docId);
					stringDocId = String.format("doc%s",
							document.getField(NAME_ID).stringValue());
					writer.write(stringQueryId + ", " + stringDocId + ", "
							+ (rank + 1) + ", " + score + newLine);
				}
				
				// Add the NGCD and MAP values
				String stats = String.format("NGCD: %s, MAP: %s %s%s", ndcg, map, newLine, newLine);
				writer.write(stats);
			}

		} catch (IOException exception) {
			Log.error(TAG, exception, true);
		}
	}
}
